package com.tangcheng.adapter.db.mybatis.plugin.sensitive.processor;

import com.tangcheng.adapter.db.mybatis.plugin.sensitive.annotation.SensitiveField;
import com.tangcheng.adapter.db.mybatis.plugin.sensitive.service.IEncryptionAlgorithm;
import com.tangcheng.adapter.db.mybatis.plugin.sensitive.util.FieldHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Slf4j
public class DecryptSensitiveField extends AbstractSensitiveField {

    public DecryptSensitiveField(IEncryptionAlgorithm encryptService) {
        this.encryptService = encryptService;
    }

    public Object preHandler(ProceedingJoinPoint pjp) throws Throwable {
        return pjp.proceed();
    }

    public Object handle(Object o) {
        log.debug("开始解密");
        Object retObj = o;
        if (o instanceof String) {
            retObj = this.encryptService.decrypt(o.toString());
        } else if (o instanceof Set) {
            Set set = (HashSet) o;
            if (FieldHelper.checkStringInCollection(set)) {
                retObj = this.handleSet(set);
            } else {
                retObj = this.handleSet(set);
            }
        } else if (o instanceof List) {
            List list = (List) o;
            if (FieldHelper.checkStringInCollection(list)) {
                retObj = this.fieldValueDecryptIfString(list);
            } else {
                retObj = this.handleList(list);
            }
        } else if (FieldHelper.checkIfObject(o.getClass().getTypeName())) {
            retObj = this.handleSingleObject(o);
        } else {
            log.warn(" 未知类型 暂未支持 {} ", o);
        }
        return retObj;
    }

    @Override
    public Object proceed(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = this.preHandler(proceedingJoinPoint);
        return this.handle(result);
    }

    private List<String> fieldValueDecryptIfString(List<String> collection) {
        List<String> result = new ArrayList<>(collection.size());
        collection.forEach((item) -> {
            if (StringUtils.isNotBlank(item)) {
                String content = item.replaceAll("[\\t\\n\\r]", "");
                if (FieldHelper.isBase64(content)) {
                    String newVal = this.encryptService.decrypt(item);
                    result.add(newVal);
                } else {
                    result.add(item);
                }
            } else {
                result.add(item);
            }

        });
        return result;
    }

    @Override
    public void setFieldValue(Object object, Field field) {
        if (field.isAnnotationPresent(SensitiveField.class)) {
            try {
                field.setAccessible(true);
                Object val = field.get(object);
                if (val != null && StringUtils.isNotBlank(val.toString())) {
                    String content = val.toString();
                    content = content.replaceAll("[\\t\\n\\r]", "");
                    if (FieldHelper.isBase64(content)) {
                        String newVal = this.encryptService.decrypt(content);
                        field.set(object, newVal);
                        log.info("敏感字段解密 字段：{} 密文：{} 明文：{}", field.getName(), val, newVal);
                    }
                }
                field.setAccessible(false);
            } catch (Exception e) {
                log.warn("解密失败 {} ", e.getMessage());
            }
        }

    }
}
